iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0
Mobile Development

【Kotlin Notes And JetPack】Build an App系列 第 21

Day 21.【Architecture】DataStore 的介紹與應用

  • 分享至 

  • xImage
  •  

如果你已經知道什麼是 Sharedpeference 那就不能不了解一下什麼是 DataStore,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:

什麼?

為一種輕量級的資料儲存方式,如果有較複雜的資料型態請使用 Room 來取代:

Note:
If you need to support large or complex datasets, partial updates, or referential integrity, consider using Room instead.

是 Google 目標用來取代 SharedPreference 的輕量型儲存方式,運用 Kotlin coroutine 及 flow 進行非同步儲存,克服一些 SharedPreference 的缺點,目前主要分成兩種儲存類別:

  • Preferences DataStore
    跟原本的 shared preference 依樣是透過 key-value pairs 的型態來儲存,無 type-safety

  • Proto DataStore
    以 typed objects 的形式作儲存(以 protocol buffers 型態序列化資料 - Google 開發的) ,實作上會比 Preferences 來得複雜許多

如何?

這次會將 DataStore 用在設定頁上,目前設定頁有一個紫外線提醒的開關,利用 DataStore 來儲存開關的是否開啟:

| Set up

先加入 dependency (Preferences 和 Proto 分別為不一樣的 dependency )

dependencies {
    ...
    implementation "androidx.datastore:datastore-preferences:1.0.0"
    implementation "androidx.datastore:datastore-core:1.0.0"
    ...
}

| 建立 DataStore 黨

// AppStored.kt
class AppStored(private val dataStore: DataStore<Preferences>) {

}

| 建立 Key Object

建立 key object,以往的 SharedPreferences 是以單純的文字當作 key,DataStore 必須建立一個 object :

class AppStored(private val dataStore: DataStore<Preferences>) {
    // DataStore
    private val UVA_WARN= booleanPreferencesKey("uva_warn")
    // SharedPreference
    private val UVA_WARN= "uva_warn"
}

| 寫入資料

寫入的 function 跟 SharedPreferences 依樣是呼叫 edit() ,但不同的是 DataStore 所提供的是 suspending function :

...
suspend fun enableUVAWarn(enable: Boolean) {
   dataStore.edit { preferences ->
      // write value
      preferences[UVA_WARN] = enable
   }
}
...

| 讀取資料

當讀取時勢必會有 error 的產生,這時可在讀取時加入 catch,如果是 IOException 可回傳 emptyPreferences(),其他類型的就建議直接拋出這個 exception:

val uvaPreferencesFlow: Flow<Boolean> = dataStore.data
    .catch { exception ->
        // dataStore.data throws an IOException when an error is encountered when reading data
        if (exception is IOException) {
            Log.e("error", "Error reading preferences.", exception)
            emit(emptyPreferences())
        } else {
            throw exception
        }
    }.map { preferences ->
        preferences[UVA_WARN]?: false
    }

| 清除資料

與 SharedPreference 相同,使用 clear() 和 remove(keyName),目前依功能不需要使用:

suspend fun clearPreferences () {
  context.dataStore.edit { preferences ->
		preferences.clear()
		// remove single 
		preferences.remove(UVA_WARN)
  }
}

| 在頁面呼叫

在設定頁操作:

// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
...

private val appStored by lazy { AppStored(requireContext().dataStore) }
...
private fun setupView() = binding.apply {
    ...
    uvaSetting.apply {
         lifecycleScope.launch {
            appStored.uvaPreferencesFlow.collect {
            isChecked = it
            }
            setOnCheckedChangeListener { _, isChecked ->
                appStored.enableUVAWarn(isChecked)
            }
        }
    }
}

Reference

DataStrore codelab
Morden Jetpack dataStore


上一篇
Day 20.【Architecture】Navigation Shared Element Transition
下一篇
Day 22.【Architecture】Room 的介紹與應用
系列文
【Kotlin Notes And JetPack】Build an App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言